/*
Copyright [2020] [https://www.xiaonuo.vip]

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Snowy采用APACHE LICENSE 2.0开源协议，您在使用过程中，需要注意以下几点：

1.请不要删除和修改根目录下的LICENSE文件。
2.请不要删除和修改Snowy源码头部的版权声明。
3.请保留源码和相关描述文件的项目出处，作者声明等。
4.分发源码时候，请注明软件出处 https://gitee.com/xiaonuobase/snowy
5.在修改包名，模块名称，项目代码等时，请注明软件出处 https://gitee.com/xiaonuobase/snowy
6.若您的项目无法满足以上几点，可申请商业授权，获取Snowy商业授权许可，请在官网购买授权，地址为 https://www.xiaonuo.vip
 */
package vip.xiaonuo.modular.customcode.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Console;
import cn.hutool.core.util.EnumUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import vip.xiaonuo.core.exception.ServiceException;
import vip.xiaonuo.core.factory.PageFactory;
import vip.xiaonuo.core.pojo.page.PageResult;
import vip.xiaonuo.core.util.PoiUtil;
import vip.xiaonuo.generate.core.util.Util;
import vip.xiaonuo.generate.modular.result.InformationResult;
import vip.xiaonuo.modular.customcode.entity.CustomCode;
import vip.xiaonuo.modular.customcode.enums.CustomCodeExceptionEnum;
import vip.xiaonuo.modular.customcode.enums.TimeFormat;
import vip.xiaonuo.modular.customcode.enums.WhitelistEnum;
import vip.xiaonuo.modular.customcode.mapper.CustomCodeMapper;
import vip.xiaonuo.modular.customcode.param.CustomCodeParam;
import vip.xiaonuo.modular.customcode.service.CustomCodeService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * 自定义编号规则service接口实现类
 *
 * @author sxy
 * @date 2022-06-28 09:32:04
 */
@Service
public class CustomCodeServiceImpl extends ServiceImpl<CustomCodeMapper, CustomCode> implements CustomCodeService {

    @Override
    public PageResult<CustomCode> page(CustomCodeParam customCodeParam) {
        QueryWrapper<CustomCode> queryWrapper = new QueryWrapper<>();
        if (ObjectUtil.isNull(customCodeParam)) {
            throw new ServiceException(3, "参数不能为空！");
        }
        if (ObjectUtil.isNotNull(customCodeParam.getTableReName())) {
            queryWrapper.lambda().like(CustomCode::getTableReName, customCodeParam.getTableReName());
        }
        if (ObjectUtil.isNotNull(customCodeParam.getEncode())) {
            queryWrapper.lambda().like(CustomCode::getEncode, customCodeParam.getEncode());
        }
        return new PageResult<>(this.page(PageFactory.defaultPage(), queryWrapper));
    }


    @Override
    public List<CustomCode> list(CustomCodeParam customCodeParam) {
        return this.list();
    }

    @Override
    public void add(CustomCodeParam customCodeParam) {
        checkParam(customCodeParam);
        // TODO next
        CustomCode customCode = new CustomCode();
        BeanUtil.copyProperties(customCodeParam, customCode);
        // TODO 处理数据，主要是customCode.setTableName存在一表多规则的情况
        String tableName = customCode.getTableName();
        Boolean isTrim = true;
        final List<String> whitelist = EnumUtil.getNames(WhitelistEnum.class);
        for (String s : whitelist) {
            if (s.equals(tableName.toUpperCase().trim())) {
                isTrim = false;
                break;
            }
        }
        if (isTrim) {
            customCode.setTableName(customCode.getTableName().trim());
        }
        // TODO 查找要保存规则是否已经存在
        LambdaQueryWrapper<CustomCode> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(CustomCode::getTableReName, customCode.getTableReName());
        final int count = this.count(queryWrapper);
        if (count == 0) {
            this.save(customCode);
            return;
        }
        throw new ServiceException(3, "此表已有规则，请勿重复添加！");
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(List<CustomCodeParam> customCodeParamList) {
        customCodeParamList.forEach(customCodeParam -> {
            this.removeById(customCodeParam.getId());
        });
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void edit(CustomCodeParam customCodeParam) {
        checkParam(customCodeParam);
        CustomCode customCode = this.queryCustomCode(customCodeParam);
        BeanUtil.copyProperties(customCodeParam, customCode);
        // TODO 处理数据，主要是customCode.setTableName存在一表多规则的情况
        String tableName = customCode.getTableName();
        Boolean isTrim = true;
        final List<String> whitelist = EnumUtil.getNames(WhitelistEnum.class);
        for (String s : whitelist) {
            if (s.equals(tableName.toUpperCase().trim())) {
                isTrim = false;
                break;
            }
        }
        if (isTrim) {
            customCode.setTableName(customCode.getTableName().trim());
        }
        // TODO 查找要编辑规则是否已经存在
        LambdaQueryWrapper<CustomCode> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(CustomCode::getTableReName, customCode.getTableReName());
        final int count = this.count(queryWrapper);
        if (count == 1) {
            this.updateById(customCode);
            return;
        }
        throw new ServiceException(3, "此表无规则！");
    }

    @Override
    public CustomCode detail(CustomCodeParam customCodeParam) {
        return this.queryCustomCode(customCodeParam);
    }

    /**
     * 获取自定义编号规则
     *
     * @author sxy
     * @date 2022-06-28 09:32:04
     */
    private CustomCode queryCustomCode(CustomCodeParam customCodeParam) {
        CustomCode customCode = this.getById(customCodeParam.getId());
        if (ObjectUtil.isNull(customCode)) {
            throw new ServiceException(CustomCodeExceptionEnum.NOT_EXIST);
        }
        return customCode;
    }

    @Override
    public void export(CustomCodeParam customCodeParam) {
        List<CustomCode> list = this.list(customCodeParam);
        PoiUtil.exportExcelWithStream("SnowyCustomCode.xls", CustomCode.class, list);
    }

    @Override
    public String getMax(String tableName, String tableFieldName, int serialNum, int totalNum, String like) {
        if (ObjectUtil.isEmpty(tableName) || ObjectUtil.isEmpty(tableFieldName) || ObjectUtil.isEmpty(serialNum) ||
                ObjectUtil.isEmpty(totalNum) || ObjectUtil.isEmpty(like)) {
            throw new NullPointerException();
        }
        return this.baseMapper.getMax(tableName, tableFieldName, serialNum, totalNum, like);
    }

    @Override
    public List<InformationResult> getInformationTable() {
        // TODO 获取数据库表名list
        List<InformationResult> list = this.baseMapper.selectInformationTableByLike(Util.getDataBasename(), "dw%");
        // TODO 收集器，收集需要删除的列表项
        Collection<InformationResult> collection = new ArrayList<>();
        // TODO 对出入库单进行单独的处理
        InformationResult result = null;
        for (InformationResult informationResult : list) {
            if ("dw_custom_code".equals(informationResult.getTableName())
                    || "dw_field_config".equals(informationResult.getTableName())
                    || "dw_inv_detail".equals(informationResult.getTableName())
                    || "dw_work_order_task".equals(informationResult.getTableName())
                    || "dw_work_step_route".equals(informationResult.getTableName())
                    || "dw_inv".equals(informationResult.getTableName())) {
                collection.add(informationResult);
            }
            if ("dw_inv".equals(informationResult.getTableName())) {
                result = informationResult;
            }
        }
        // TODO 删除收集器里的列表项
        list.removeAll(collection);
        // TODO 把出入库单拆成出库单和入库单
        if (ObjectUtil.isNotNull(result)) {
            result.setTableComment("出库单");
            list.add(result);
            InformationResult _result = new InformationResult();
            _result.setTableName(" " + result.getTableName());
            _result.setTableComment("入库单");
            list.add(_result);
        }
        return list;
    }

    @Override
    public List<String> getCodeList(String tableName, String tableFieldName, int start, int serialNum, int totalNum, String like, int limit, String prefix, String suffix) {
        if (ObjectUtil.isEmpty(tableName) || ObjectUtil.isEmpty(tableFieldName) || ObjectUtil.isEmpty(serialNum) ||
                ObjectUtil.isEmpty(totalNum) || ObjectUtil.isEmpty(like) || ObjectUtil.isEmpty(limit)) {
            throw new NullPointerException();
        }
        return this.baseMapper.getCodeList(tableName, tableFieldName, start, serialNum, totalNum, like, limit, prefix, suffix);
    }

    /**
     * 检查参数
     *
     * @param customCodeParam 用户传过来的参数
     * @author sxy
     * @date 9:46 2022/6/29
     **/
    private void checkParam(CustomCodeParam customCodeParam) {
        // TODO 判空
        if (ObjectUtil.isNull(customCodeParam) || ObjectUtil.isEmpty(customCodeParam)) {
            throw new ServiceException(CustomCodeExceptionEnum.NOT_EXIST);
        }
        // TODO 检查参数属性
        if (customCodeParam.getTimeFormat() != TimeFormat.YEAR.timeFormatValue
                && customCodeParam.getTimeFormat() != TimeFormat.YEAR_MONTH.timeFormatValue
                && customCodeParam.getTimeFormat() != TimeFormat.YEAR_MONTH_DAY.timeFormatValue
                && customCodeParam.getTimeFormat() != TimeFormat.NOTHING.timeFormatValue) {
            throw new ServiceException(3, "Invalid time format");
        }
        if (ObjectUtil.isNull(customCodeParam.getTableReName()) || ObjectUtil.isEmpty(customCodeParam.getTableReName())) {
            throw new ServiceException(3, "Invalid is null");
        }
    }


}
